package com.zmj.sy.mom.srv.aps.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictData;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictType;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.dictdata.*;
import com.zmj.sy.mom.srv.aps.config.RedisKeyConfiguration;
import com.zmj.sy.mom.srv.aps.mapper.DictDataMapper;
import com.zmj.sy.mom.srv.aps.mapper.DictTypeMapper;
import com.zmj.sy.mom.srv.aps.utils.MkBeanUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class DictDataService {

    private final DictDataMapper dictDataMapper;

    private final DictTypeMapper dictTypeMapper;

    private final RedisKeyConfiguration redisKeyConfiguration;

    private final StringRedisTemplate redisTemplate;

    private final ObjectMapper objectMapper;


    public void add(DictDataAddReqVo reqVo) {
        // 判断字典类型是否已存在
        DictType dictType = dictTypeMapper.selectOne(Wrappers.<DictType>query().eq("id", reqVo.getDictType()));
        if (dictType == null) {
            throw SyExceptionUtils.e("字典类型不存在");
        }


        DictData dd = new DictData();
        BeanUtils.copyProperties(reqVo, dd);
        dictDataMapper.insert(dd);

        clearRedisCache(dictType.getDictCode());
    }

    public void edit(DictDataEditReqVo reqVo) {
        DictType dictType = dictTypeMapper.selectOne(Wrappers.<DictType>query().eq("id", reqVo.getDictType()));
        if (dictType == null) {
            throw SyExceptionUtils.e("字典类型不存在");
        }

        DictData dd = new DictData();
        BeanUtils.copyProperties(reqVo, dd);
        dictDataMapper.updateById(dd);

        clearRedisCache(dictType.getDictCode());
    }

    public void delete(BaseIdReqVo reqVo) {
        dictDataMapper.deleteById(reqVo.getId());
    }

    public DictDataGetResVo get(BaseIdReqVo reqVo) {
        DictData dictData = dictDataMapper.selectById(reqVo.getId());
        DictDataGetResVo resVo = new DictDataGetResVo();
        BeanUtils.copyProperties(dictData, resVo);
        return resVo;
    }

    public List<DictDataFindResVo> find(DictDataFindReqVo reqVo) {
        QueryWrapper<DictData> query = Wrappers.query();
        if(reqVo.getDictTypeId() != null){
            query.eq("dt.id", reqVo.getDictTypeId());
        } else {
            query.eq("dt.dict_code", reqVo.getDictTypeCode());
        }
        query.eq("dd.deleted", 0);
        List<DictData> byDictTypeCode = dictDataMapper.findByDictTypeCode(query);
        return byDictTypeCode
                .stream()
                .map(e -> MkBeanUtils.copyProperties(e, DictDataFindResVo.class))
                .sorted(Comparator.comparing(DictDataFindResVo::getDictSort))
                .collect(Collectors.toList());
    }

    @SneakyThrows
    public List<DictDataFindResVo> find(String dictTypeCode) {
        String s = redisTemplate.opsForValue().get(redisKeyConfiguration.getDictTypeKeyPrefix() + dictTypeCode);

        if (s != null) {
            return objectMapper.readValue(s, new TypeReference<ArrayList<DictDataFindResVo>>() {});
        }

        QueryWrapper<DictData> query = Wrappers.query();
        query.eq("dt.dict_code", dictTypeCode);
        List<DictData> byDictTypeCode = dictDataMapper.findByDictTypeCode(query);
        List<DictDataFindResVo> collect = byDictTypeCode
                .stream()
                .map(e -> {
                    DictDataFindResVo resVo = new DictDataFindResVo();
                    BeanUtils.copyProperties(e, resVo);
                    return resVo;
                })
                .sorted(Comparator.comparing(DictDataFindResVo::getDictSort))
                .collect(Collectors.toList());

        redisTemplate.opsForValue().set(redisKeyConfiguration.getDictTypeKeyPrefix() + dictTypeCode, objectMapper.writeValueAsString(collect), 1, TimeUnit.DAYS);
        return collect;
    }

    public void clearRedisCache(String dictTypeCode) {
        redisTemplate.delete(redisKeyConfiguration.getDictTypeKeyPrefix() + dictTypeCode);
    }


}
